<template>
    <div class="bpm-inst-container">
        <div class="bpm-inst-content" style="flex: 1;">
            <a-collapse defaultActiveKey="user" v-if="assignFlowUsers" class="bpm-collapse">
                <a-collapse-panel key="user" :header="i18n('instStart.assignFlowUsers','指定人员')">
                    <a-form-item v-for="reqNode in startReqNodes"
                                 :key="reqNode.nodeId"
                                 :label="reqNode.nodeName"
                                 class="bpm-form-item"
                                 :colon="false"
                    >
                        <rx-text-list v-model="reqNode.users" textfield="name" valuefield="id"
                                      @click="selectUsers(reqNode)" style="margin-top: 6px">
                            <my-icon v-if="reqNode.allowSelectExecutor" type="iconuser-account-add"></my-icon>
                        </rx-text-list>
                    </a-form-item>
                </a-collapse-panel>
            </a-collapse>
            <a-collapse defaultActiveKey="nodeUser" v-if="batchNodes.length>0" class="bpm-collapse">
                <a-collapse-panel key="nodeUser" :header="i18n('instStart.assignBatchNodeFlowUsers','指定批次节点人员')">
                    <a-form-item
                        v-for="batchNode in batchNodes"
                        :key="batchNode.nodeId"
                        :label="batchNode.nodeName">
                        <div v-for="(batch,index) in batchNode.batchGroups"
                             :class="{'bpm-item-div':true,'bpm-item-div-edit':batch.isNew}">
                            <div class="bpm-header-toolbar">
                                <div>
                                    <a-input v-if="batch.isNew" v-model:value="batch.name"
                                             :placeholder="i18n('instStart.batchName','请输入批次名称','input')"/>
                                    <span v-else>{{ batch.name }}</span>
                                </div>
                                <div class="bpm-toolbar-right">
                                    <div class="bpm-toolbar-right-select">
                                        <a-select v-if="batch.isNew" v-model:value="batch.executeType"
                                                  :options="executeOptions" size='small' style="width:100px;"/>
                                        <a-tag v-else :color="executeTypeMap[batch.executeType].color">
                                            {{ executeTypeMap[batch.executeType].text }}
                                        </a-tag>
                                    </div>
                                    <my-icon v-if="batchNode.batchOptions.includes('allowDel')"
                                             style="cursor: pointer;color:red;"
                                             :title="$ti18('rxList.delBtn','删除')" @click="removeBatch(batchNode,index)"
                                             type="iconVue3_delete"></my-icon>
                                </div>
                            </div>
                            <rx-text-list
                                v-model="batch.users"
                                textfield="name"
                                valuefield="id"
                                @click="selectUsers(batch)"
                                style="margin-top: 6px"
                                :readonly="!batch.allowSelectUser"
                            >
                                <my-icon type="iconuser-account-add"></my-icon>
                            </rx-text-list>
                        </div>
                        <div class="bpm-add-button-content" v-if="batchNode.batchOptions.includes('allowAdd')">
                            <span class="bpm-add-button" @click="addBatch(batchNode)">
                                <PlusCircleOutlined/>
                                <span>{{ i18n('instStart.newBatch', '新增批次') }}</span>
                            </span>
                        </div>
                    </a-form-item>
                </a-collapse-panel>
            </a-collapse>

            <a-form-item :label="i18n('list.assoProcess','关联流程')" v-if="showRelInsts">
                <rx-text-list v-model="relInsts"
                              :showclose="true"
                              :readonly="false"
                              valuefield="id" textfield="name"
                              @click="selectBpmInst()"
                >
                    <my-icon type="iconuser-account-add"></my-icon>
                </rx-text-list>

            </a-form-item>
            <a-form-item :label="i18n('instStart.aboutFlow','即将流向')" v-if="processConfig.allowSelectPath">
                <bpm-task-executors
                    ref="taskExecutors"
                    :nodeExecutors="nodeExecutors"
                    :allow-select-executor="true"
                    :processConfig="processConfig"
                ></bpm-task-executors>
            </a-form-item>
            <a-form-item :label="i18n('instStart.description','提交说明')" v-if="fillOpinion==true">
                <rx-tribute ref="rxtribute" style="height:100px;margin-top: 10px"></rx-tribute>
            </a-form-item>
            <a-form-item :label="i18n('form.appendix','附件')" v-if="fillOpinion==true">
                <rx-attach-component v-model="fileList"></rx-attach-component>
            </a-form-item>
        </div>
        <div style="padding:10px;text-align: center;">
            <a-button @click="submitForm" :loading="loading" style="margin-right: 6px;" type="primary">
                {{ $ti18('rxForm.okBtn', '确定') }}
            </a-button>
            <a-button @click="cancel">{{ $ti18('rxForm.cancelBtn', '取消') }}</a-button>
        </div>
    </div>
</template>
<script>
import {Util, RxSpin, RxTextList} from "@lowcode/jpaas-base-lib";
import {ShareDialog, RxAttachComponent} from '@lowcode/jpaas-share-component';
import BpmInstApi from "@/common/api/bpm/bpmInst";
import BpmDefApi from '@/common/api/bpm/bpmDef';
import BpmTaskExecutors from "../components/BpmTaskExecutors.vue";
import BpmMyEvents from "./dialog/BpmMyEvents.vue";
import RxTribute from "@/views/modules/bpm/tribute/rx-tribute.vue";

export default {
    name: 'BpmInstStartConfirm',
    props: {
        /**
         * 表单方案别名
         */
        formSolutionAlias: {type: String},
        /**
         * 流程全局配置
         */
        processConfig: {type: Object, required: true},
        /**
         * 流程定义ID
         */
        defId: {type: String},
        /**
         * 流程实例ID
         */
        instId: {type: String},
        /**
         * 表单数据
         */
        formData: {
            type: Object, default: () => {
            }
        },
        //幂等号
        idempotenceid:{type:String},

        layerid: String,
        destroy: Function
    },
    components: {
        RxTribute,
        RxSpin,
        RxTextList,
        RxAttachComponent,
        BpmTaskExecutors,
        BpmMyEvents
    },
    data() {
        return {
            //填写意见
            fillOpinion: false,
            //配置后续用户
            assignFlowUsers: false,
            //计算后续执行用户
            startCalFlowusers: false,
            //是否显示指定关联流程
            showRelInsts: false,
            batchNodes: [],//批次节点
            startReqNodes: [],//必填节点项
            nodeUsers: [],//后续节点人员Id列表,
            spinShow: false,
            nodeExecutors: [],
            fileList: [],
            relInsts: [],
            opinion: "",
            executeOptions: [
                {value: "normal", label: this.i18n("instStart.normal", "抢签")},
                {value: "parallel", label: this.i18n("instStart.parallel", "并行")},
                {value: "sequential", label: this.i18n("instStart.sequential", "串行")}
            ],
            executeTypeMap: {
                normal: {color: "orange", text: this.i18n("instStart.normal", "抢签")},
                parallel: {color: "blue", text: this.i18n("instStart.parallel", "并行")},
                sequential: {color: "green", text: this.i18n("instStart.sequential", "串行")}
            },
            loading: false
        }
    },
    created() {

    },
    methods: {
        i18n(name, text, key) {
            return this.$ti18(name, text, "bpmInst", key);
        },
        addBatch(batchNode) {
            batchNode.batchGroups.push({
                isNew: true,
                name: "",
                executeType: "normal",
                condition: "",
                allowSelectUser: true,
                users: []
            });
        },
        removeBatch(batchNode, index) {
            batchNode.batchGroups.splice(index, 1);
        },
        //选择对话框
        selectUsers(reqNode) {
            var self = this;
            let rtUsers = reqNode.users;
            let single = reqNode.single;
            let selectUsers = [];
            for (let i = 0; i < rtUsers.length; i++) {
                selectUsers.push({
                    userId: rtUsers[i].id,
                    fullName: rtUsers[i].name
                })
            }
            let conf = {curVm: this, data: {single: single, data: selectUsers}, widthHeight: ['1024px', '600px']};
            ShareDialog.openUserDialog(conf, function (users) {
                if (single) {
                    reqNode["users"] = [{name: users.fullName, id: users.userId, account: users.userNo, type: "user"}];
                } else {
                    let userInfos = users.map(item => {
                        return {
                            id: item.userId,
                            name: item.fullName,
                            account: item.userNo,
                            type: "user"
                        }
                    })
                    reqNode["users"] = userInfos;
                }
            });
        },
        getNodeUsers() {
            let nodeUserIds = {};
            //节点人员是否设置了
            let isNodeUserSet = true;
            //检查是否有存在的节点人员必须需要
            if (this.assignFlowUsers) {
                for (let i = 0; i < this.startReqNodes.length; i++) {
                    var node = this.startReqNodes[i];
                    if (node.users.length == 0) {
                        isNodeUserSet = false;
                        break;
                    }
                    let userIds = [];
                    node.users.forEach(item => {
                        userIds.push(item.id);
                    });
                    nodeUserIds[node.nodeId] = userIds.join(',');
                }

            }
            return {nodeUserIds: nodeUserIds, isNodeUserSet: isNodeUserSet};
        },
        getFormData() {
            let data = {defId: this.defId};
            let formJson = JSON.stringify(this.formData);
            data.formJson = formJson;
            if (this.instId) {
                data.instId = this.instId;
            }
            data.formSolutionAlias = this.formSolutionAlias;
            if(this.idempotenceid){
                data.idempotenceid = this.idempotenceid;
            }
            return data;
        },
        getSubmitData(objNodeUsers) {

            let data = this.getFormData();
            data.checkType = "AGREE";
            data.opFiles = JSON.stringify(this.fileList);
            data.relInsts = JSON.stringify(this.relInsts);
            var rxtribute = this.$refs.rxtribute;
            if(rxtribute){
                data.opinion = rxtribute.getOpinion();
                data.linkupAccounts = rxtribute.getLinkup();
            }
            //是否已有主键。
            var hasPk = this.processConfig.hasPk;
            if (hasPk) {
                data.systemHand = true;
                data.hasPk = true;
            }

            if (this.processConfig.assignBatchFlowUsers) {
                let batchNodeGroups = {};
                for (let i = 0; i < this.batchNodes.length; i++) {
                    var node = this.batchNodes[i];
                    if (!node.allowExecutorNull && (node.batchGroups.length == 0 || node.batchGroups[0].users.length == 0)) {
                        this.$message.error(this.i18n('msa.batchNodeTips', '批次节点必须配置批次组人员！'));
                        return {success: false};
                    }
                    batchNodeGroups[node.nodeId] = node.batchGroups;
                }
                data["batchNodeGroups"] = JSON.stringify(batchNodeGroups);
            }
            data.nodeUserIds = JSON.stringify(objNodeUsers.nodeUserIds);
            //选择执行路径
            if (this.processConfig.allowSelectPath) {
                var ctlUsers = this.$refs.taskExecutors;
                var destNodeId = ctlUsers.getDestNodeId();
                var userMap = ctlUsers.getNodeUserMap();
                data.nodeExecutors = userMap;
                data.destNodeId = destNodeId;
            }
            if (this.instId) {
                data.instId = this.instId;
            }
            return {success: true, data: data};
        },
        async submitForm(e) {
            this.loading = true
            let self = this;
            var objNodeUsers = this.getNodeUsers();
            if (!objNodeUsers.isNodeUserSet) {
                this.$message.error(self.i18n('msa.requiredNodeTips', '必填节点没有选择人员！'));
                self.loading = false;
                return;
            }
            //获取当前需要提交的数据。
            var result = this.getSubmitData(objNodeUsers);
            if (!result.success) {
                self.loading = false;
                return;
            }
            self.spinShow = true;
            BpmInstApi.startProcess(result.data).then(data => {
                self.spinShow = false;
                if (data.success) {
                    Util.closeWindow(self, 'ok', data);
                    self.loading = false;
                }
            }).catch((error) => {
                self.spinShow = false;
                self.loading = false;
            }).finally(() => {
                self.loading = false;
            });
        },

        cancel() {
            Util.closeWindow(this, 'cancel');
        },
        getBatchUserNodes() {
            let self = this;
            //传入 defId 则可
            var formData = this.getFormData().formJson;

            BpmDefApi.getBatchUserNodes(this.defId, formData).then(resp => {
                self.batchNodes = [];
                resp.forEach(item => {
                    let {options, groups} = item.batchGroup;
                    self.batchNodes.push({
                        nodeId: item.nodeId,
                        nodeName: item.name,
                        allowExecutorNull: item.allowExecutorNull,
                        i18nJson: item.i18nJson,
                        batchOptions: options || [],
                        batchGroups: groups || []
                    });
                });
            });
        },
        getStartUserNodes() {
            let self = this;
            //传入 defId 则可
            var formData = this.getFormData().formJson;

            BpmDefApi.getStartUserNodes(this.defId, formData).then(resp => {
                self.startReqNodes = [];
                resp.forEach(item => {
                    self.startReqNodes.push({
                        nodeId: item.nodeId,
                        nodeName: item.name,
                        users: item.users,
                        single: item.singleExecutor,
                        allowSelectExecutor: item.allowSelectExecutor
                    });
                });
            });
        },
        getFlowNodesExecutors() {
            //传入 defId 则可
            var formData = this.getFormData().formJson;
            BpmDefApi.getFlowNodesExecutors(this.defId, formData).then(res => {
                for (var i = 0; i < res.length; i++) {
                    var o = res[i];
                    o.selected = i == 0;
                }
                this.nodeExecutors = res;
            })
        },
        selectBpmInst() {
            var conf = {
                component: BpmMyEvents,
                title: this.i18n('list.assoProcess', '关联流程'),
                curVm: this, widthHeight: ['1024px', '600px']
            };
            var self_ = this;
            Util.open(conf, function (action, relInsts) {
                if (action != 'ok') return;

                var idAry = [];
                for (var i = 0; i < self_.relInsts.length; i++) {
                    var o = self_.relInsts[i];
                    idAry.push(o.id);
                }

                for (var i = 0; i < relInsts.length; i++) {
                    var o = relInsts[i];
                    if (idAry.includes(o.id)) {
                        continue;
                    }
                    self_.relInsts.push(o);
                }
            });
        }
    },
    watch: {
        batchNodes: {
            handler(newVal) {
                if (!newVal) {
                    return;
                }
                let batchNodeMap = {};
                newVal.forEach(item => {
                    if (item.batchGroups && item.batchGroups.length > 0) {
                        batchNodeMap[item.nodeId] = item.batchGroups[0].users;
                    } else {
                        batchNodeMap[item.nodeId] = [];
                    }
                })
                for (let i = 0; i < this.nodeExecutors.length; i++) {
                    let node = this.nodeExecutors[i];
                    let nodeUsers = batchNodeMap[node.nodeId];
                    if (nodeUsers) {
                        node.executors = nodeUsers;
                    }
                }
            },
            deep: true
        },
        processConfig: {
            handler(newVal, oldVal) {
                if (!newVal) {
                    return;
                }
                this.buttons = newVal.buttons;
                if (newVal.startNodeOptions instanceof Array) {
                    this.startConfirm = newVal.startNodeOptions.indexOf('startConfirm') != -1;
                    this.fillOpinion = newVal.startNodeOptions.indexOf('fillOpinion') != -1;
                    //执行下一步用户。
                    this.assignFlowUsers = newVal.startNodeOptions.indexOf('assignFlowUsers') != -1;
                    this.startCalFlowusers = newVal.startNodeOptions.indexOf('startCalFlowusers') != -1;
                    this.showRelInsts = newVal.startNodeOptions.indexOf('relInsts') != -1;

                }
                //是否需要显示弹出的窗口
                if (this.assignFlowUsers) {
                    this.getStartUserNodes();
                }
                if (newVal.allowSelectPath) {
                    this.getFlowNodesExecutors();
                }
                if (newVal.assignBatchFlowUsers) {
                    this.getBatchUserNodes();
                }

            },
            immediate: true
        },
    }
}
</script>
<style scoped>
.bpm-inst-container {
    width: 100%;
    height: 100%;

    display: flex;
    flex-direction: column;
}

.bpm-inst-content {
    overflow: auto;
    flex: 1;
    padding: 10px;
    border-bottom: 1px solid #ddd;
}

.bpm-item-div {
    padding-bottom: 10px;
    margin-bottom: 6px;
}

.bpm-item-div-edit {
    background-color: #f7f7f7;
    border-radius: 4px;
    padding: 10px;
}

.bpm-toolbar-right-select >>> .ant-tag {
    margin-right: 0;
}

.bpm-toolbar-right-select {
    padding-right: 10px;
    display: flex;
    align-items: center;
}

.bpm-toolbar-right {
    display: flex;
    align-items: center;
    padding-bottom: 4px;
}

.bpm-header-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    line-height: normal;
}

.bpm-collapse >>> .ant-form-item {
    margin-bottom: 14px;
}

.bpm-form-item >>> .ant-form-item-label {
    line-height: normal;
}

.bpm-collapse {
    border: 0;
    background: #fff;
}

.bpm-collapse >>> .ant-collapse-item {
    border-bottom: 0;
}

.bpm-collapse >>> .ant-collapse-item > .ant-collapse-header {
    padding: 6px 6px 6px 20px;
}

.bpm-collapse >>> .ant-collapse-item > .ant-collapse-header .ant-collapse-arrow {
    margin-top: 1px;
    left: 0;
}

.bpm-collapse >>> .ant-collapse-content > .ant-collapse-content-box {
    padding: 0;
}

.bpm-collapse >>> .ant-collapse-content {
    border-top: 0;
}

.divider {
    font-size: 14px;
    position: relative;
    margin: 10px 0;
}

.divider > span {
    display: inline-block;
    position: relative;
    z-index: 10;
    background: #fff;
    padding: 0 10px;
    font-weight: bold;
}

.divider > span:before {
    content: '';
    display: inline-block;
    height: 14px;
    background: #4D9EFF;
    width: 3px;
    position: absolute;
    left: 0;
    top: 50%;
    margin-top: -6px;
}

.divider:after {
    content: '';
    position: absolute;
    top: 50%;
    right: 0;
    width: 100%;
    display: block;
    border-bottom: 1px solid #e8e8e8;
    z-index: 8;
}

.bpm-add-button {
    cursor: pointer;
    color: #4d9eff;
}

.bpm-add-button i {
    padding: 4px 6px;
}
</style>
